package com.linjiahao.oss.aop;

import com.alibaba.fastjson.JSON;
import com.linjiahao.oss.util.StateSecretSecurityUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * 国密防篡改AOP
 * @author suruihuang
 */
@Aspect
@Component
@Order(1)
public class StateSecretTamperProofAop {
    private final static transient Logger logger = LoggerFactory.getLogger(com.linjiahao.oss.aop.StateSecretTamperProofAop.class);

    @Autowired
    private StateSecretSecurityUtil stateSecretSecurityUtil;
    

    //启用国密标志,1:启用,0:禁用
    private static String ENABLE_STATE_SECRET="1";

    
    public static String stateSecretSignMethodPrefix = "update|insert|modify|add|execBatch";

    public static String[] signMethodPrefixArr=null;

    @Pointcut("(execution(* com.linjiahao.oss.service.*.*(..)))")
    private void tamperProof() {}

    @Around("tamperProof()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable{
        Date startTime=new Date();
        //执行方法前
        Signature signature = point.getSignature();
        // 方法名
        String methodName = signature.getName();
        // 类名
        String serviceName = signature.getDeclaringTypeName();
        // 参数名数组
        String[] parameterNames = ((MethodSignature) signature).getParameterNames();

        //构造参数值
        Object args[]=point.getArgs();

        // 构造参数组集合
        List<Object> argList = stateSecretSecurityUtil.toListJSON(args);

        if(needSign(methodName)==true){
            if(args!=null&&args.length>0){
                //签名
                stateSecretSecurityUtil.dealSign(args);
            }
        }

        //执行方法
        Object result = point.proceed();

        //执行方法后
        if(result!=null){
            //验签
            stateSecretSecurityUtil.dealVerifySign(result);
        }

        //执行方法后
        Date endTime=new Date();
        try {
            logger.info("\n国密防篡改AOP\n日志ID:{}\n类名:{}\n方法:{}\n请求参数:{}\n请求数据[{}]:{}\n返回数据[{}]:{}\n耗时:{}毫秒\n", Thread.currentThread().getId(),serviceName, methodName, JSON.toJSON(parameterNames), startTime, JSON.toJSON(argList),endTime,JSON.toJSON(result),endTime.getTime()-startTime.getTime());
        } catch (Exception e) {
            logger.error("国密防篡改AOP记录日志失败: {}",e.getMessage());
        }

        argList.clear();
        argList=null;

        return result;
    }

    /**
     * 判断方法名是否需要签名
     * @param methodName
     * @return
     */
    private boolean needSign(String methodName){
        if(signMethodPrefixArr==null){
            signMethodPrefixArr=stateSecretSignMethodPrefix.split("\\|",-1);
        }
        for(String prefix:signMethodPrefixArr){
            if(methodName.startsWith(prefix)){
                return true;
            }
        }
        return false;
    }
}
